---@class NChess.RoomBase : Base.RoomBase
---@field public board integer[][]
---@field public last_print_w_id integer
---@field public last_print_b_id integer
---@field public extra_pieces table
local RoomBase = Fk.Base.RoomBase:subclass("NChess.RoomBase")

local Ch = require "packages.chess-games.nchess"
local ReqPlayChess = require "packages.chess-games.nchess.core.handler.playchess"

function RoomBase:initialize()
  Fk.Base.RoomBase.initialize(self)

  self.board = Ch:createBoard()
  self.last_print_b_id = -21
  self.last_print_w_id = 21
  self.extra_pieces = {}
  self:addRequestHandler("NChess.PlayChess", ReqPlayChess)
end

function RoomBase:movePieceTo(pieceId, fromX, fromY, x, y)
  local id = self.board[fromY][fromX]
  local special_rule = {}
  if id ~= pieceId or id == 0 then return end

  --王车易位
  if Ch:getPieceById(pieceId).name == "king" and math.abs(x - fromX) > 1 then
    local myColor = Ch:getPieceById(pieceId):getColor()
    local yRook = myColor == "white" and 8 or 1
    local xRook_o = x == 3 and 1 or 8
    local xRook = x == 3 and 4 or 6
    local rook = self.board[yRook][xRook_o]
    self.board[yRook][xRook_o] = 0
    self.board[yRook][xRook] = rook
    special_rule = { type = "castling", data = {
      rookId = rook,
      fromX = xRook_o,
      fromY = yRook,
      x = xRook,
      y = yRook,
    } }
  end

  --吃过路兵
  if Ch:getPieceById(pieceId).name == "pawn" and math.abs(y - fromY) > 1 then
    local mark = pieceId
    self:setBanner("passed_pawn", mark)
  else
    self:setBanner("passed_pawn", 0)
  end

  if Ch:getPieceById(pieceId).name == "pawn" and (y - fromY) * (x - fromX) ~= 0 and self.board[y][x] == 0 then --吃过路兵条件
    local pawnId = self.board[fromY][x]
    if pawnId ~= 0 then
      local pawn = Ch:getPieceById(pawnId)
      local myColor = Ch:getPieceById(pieceId):getColor()
      if myColor ~= pawn:getColor() and pawn.name == "pawn" then
        self.board[fromY][x] = 0
        special_rule = { type = "en_passant", data = {
          pawnId = pawnId,
          fromY = fromY,
          fromX = fromX
        } }
      end
    end
  end


  self.board[fromY][fromX] = 0
  self.board[y][x] = pieceId
  return special_rule
end

function RoomBase:movePieceOut(pieceId, fromX, fromY)
  self.board[fromY][fromX] = 0
end

function RoomBase:canMoveTo(board, fromX, fromY, x, y)
  local piece = Ch:getPieceById(board[fromY][fromX])
  return piece:canMoveTo(board, fromX, fromY, x, y)
end

function RoomBase:beenMoved(pieceId)
  local pieces = self:getBanner("moved_pieces") or {}
  return table.contains(pieces, pieceId)
end

function RoomBase:getPassedPawn()
  return self:getBanner("passed_pawn") or 0
end

function RoomBase:serialize()
  local o = Fk.Base.RoomBase.serialize(self)
  o.board = self.board
  o.last_print_b_id = self.last_print_b_id
  o.last_print_w_id = self.last_print_w_id
  local ex_pieces = {}
  for k, v in pairs(self.extra_pieces) do
    table.insert(ex_pieces, { k, v.name, k > 0 and "white" or "black" })
  end
  o.extra_pieces = ex_pieces
  return o
end

function RoomBase:deserialize(o)
  Fk.Base.RoomBase.deserialize(self, o)
  self.board = o.board
  self.last_print_b_id = -21
  self.last_print_w_id = 21
  for _, arr in ipairs(o.extra_pieces) do
    local p = self:printPiece(arr[2], arr[3])
    print(p.id)
  end
end

function RoomBase:printPiece(name, color, id)
  local piece = Ch:clonePiece(name, color)
  id = id or 0
  if id == 0 then
    if color == "white" then
      id = self.last_print_w_id
      piece.id = id
      self.last_print_w_id = self.last_print_w_id + 1
    elseif color == "black" then
      id = self.last_print_b_id
      piece.id = id
      self.last_print_b_id = self.last_print_b_id - 1
    end
  end
  self.extra_pieces[id] = piece
  return piece
end

function RoomBase:addPieceTo(pieceId, x, y)
  self.board[y][x] = pieceId
end

function RoomBase:listExtraPieces()
  local ex_pieces = {}
  for k, v in pairs(self.extra_pieces) do
    table.insert(ex_pieces, { k, v.name, k > 0 and "white" or "black" })
  end
  return ex_pieces
end

function RoomBase:getPENCode()
  local pen = ""
  local board = self.board
  local role = Self.role == "white" and "b" or "w"
  local positionDict = {}

  for y, xArr in ipairs(board) do
    local spaces = 0
    for x, id in ipairs(xArr) do
      if id == 0 then
        spaces = spaces + 1
      else
        positionDict[id] = {x, y}
        if spaces > 0 then
          pen = pen .. tostring(spaces)
          spaces = 0
        end
        pen = pen .. Ch.piecePENCodeList[id > 0 and "white" or "black"][Ch:getPieceById(id).name]
      end
    end
    if spaces > 0 then
      pen = pen .. tostring(spaces)
    end
    if y < 8 then
      pen = pen .. "/"
    end
  end

  local canCastle = ""
  if not self:beenMoved(Ch.wK) then
    if not self:beenMoved(Ch.wR2) then
      canCastle = canCastle .. "K"
    end
    if not self:beenMoved(Ch.wR1) then
      canCastle = canCastle .. "Q"
    end
  end
  if not self:beenMoved(Ch.bK) then
    if not self:beenMoved(Ch.bR2) then
      canCastle = canCastle .. "k"
    end
    if not self:beenMoved(Ch.bR1) then
      canCastle = canCastle .. "q"
    end
  end
  if canCastle == "" then
    canCastle = "-"
  end

  local canEnPassant = "-"
  local passed_pawn = self:getBanner("passed_pawn")
  if passed_pawn ~= 0 and positionDict[passed_pawn] then
    local step = passed_pawn > 0 and 1 or -1
    local xPos, yPos = positionDict[passed_pawn][1], positionDict[passed_pawn][2]
    canEnPassant = Ch.AlphabetNumbers[xPos] .. tostring(9 - yPos - step)
  end

  pen = pen .. " " .. role .. " " .. canCastle .. " " .. canEnPassant

  local turnsCount = self:getBanner("RoundCount")
  local halfTurnsCount = ((turnsCount - 1) * 2 ) + (role == "w" and 0 or 1)

  pen = pen .. " " .. tostring(halfTurnsCount) .. " " .. tostring(turnsCount)

  return pen
end

return RoomBase
